#!/usr/bin/env perl
use warnings;
use strict;
#
# Copyright (C) 2017-2019 Hamish Coleman
#
# Read through a descriptions file on input and auto generate a list of rules
# for building the various files on output
#
# Each rule input line generates two dependancies:
#       $filename.orig from $depname.orig using macro rule_$rule_extract
#       $depname from $filename using macro rule_$rule_insert
#
# TODO:
# - this currently hardcods a dependancy on .config for every generated rule
#   - which could be relaxed with some work
#   - also, hardcoding it might not be the nicest method

my @entries;

while(<>) {
    s/^#.*//; # remove comment lines
    next if (m/^$/);

    if (!m/^(\S+)\s+(\S+)\s+(.*)/) {
        # if we dont have three space-separated fields, skip the line
        next;
    }

    my $entry = {};
    $entry->{generator_file} = $ARGV;
    $entry->{generator_line} = $.;
    $entry->{filename} = $1;
    $entry->{tags_raw} = $2;
    $entry->{description} = $3;

    for my $tv (split(/,/,$entry->{tags_raw})) {
        my ($tag,$val_raw) = split(/:/,$tv);
        if (!defined($val_raw)) {
            warn("Missing tag value");
            next;
        }
        my @values = split(/;/,$val_raw);

        push @{$entry->{tags}{$tag}}, @values;
    }

    # default tags - if there is a value loaded from the tags_raw, it will
    # take precedence, but otherwise this ensures we create the array and
    # have the default value at [0]
    push @{$entry->{tags}{extract}},1;
    push @{$entry->{tags}{insert}},1;
    push @{$entry->{tags}{suffix}},1;

    push @entries,$entry;
}

my $rules_found = 0;

my @extracts;
my @inserts;

for my $entry (@entries) {
    # only generate rules for lines that ask for them
    next if (!defined($entry->{tags}{rule}));

    # FIXME - if there is more than one rule, error?

    # currently need at least one dep defined
    next if (!defined($entry->{tags}{dep}));

    $rules_found++;

    my @deps = @{$entry->{tags}{dep}};
    my $dep0 = shift @deps;

    my @deps_extract;
    if (defined($entry->{tags}{depe})) {
        @deps_extract = @{$entry->{tags}{depe}};
    }

    my @deps_insert;
    if (defined($entry->{tags}{depi})) {
        @deps_insert = @{$entry->{tags}{depi}};
    }

    my @params;
    if (defined($entry->{tags}{param})) {
        @params = @{$entry->{tags}{param}};
    }

    if ($entry->{tags}{extract}[0]) {
        # generate the forward rule

        my $suffix = "";
        if ($entry->{tags}{suffix}[0]) {
            $suffix = ".orig";
        }

        my $rule = "rule_".$entry->{tags}{rule}[0]."_extract";
        push @extracts,
            sprintf("# %s:%i\n",
                $entry->{generator_file},
                $entry->{generator_line},
            ),
            sprintf("%s: %s %s %s\n\t\$(call %s)\n\n",
                $entry->{filename}.$suffix,
                $dep0.$suffix,
                join(' ',
                    @deps,
                    @deps_extract,
                    $entry->{generator_file},
                    '.config',
                ),
                '$('.$rule.'_DEPS)',
                join(',',$rule,@params),
            );
    }

    if ($entry->{tags}{insert}[0]) {
        # generate the inverse rule
        my $rule = "rule_".$entry->{tags}{rule}[0]."_insert";
        push @inserts,
            sprintf("# %s:%i\n",
                $entry->{generator_file},
                $entry->{generator_line},
            ),
            sprintf("%s: %s %s %s\n\t\$(call %s)\n\n",
                $dep0,
                $entry->{filename},
                join(' ',
                    @deps,
                    @deps_insert,
                    $entry->{generator_file},
                    '.config',
                ),
                '$('.$rule.'_DEPS)',
                join(',',$rule,@params),
            );
    }
}

if (!$rules_found) {
    # only generate output if we have at least one matching line - so an empty input
    # will just result in an empty output
    exit(0);
}

print("# autogenerated rules file - do not edit\n\n");
print(join('',@extracts));
print("\n\n");
print(join('',@inserts));

print STDERR "Generated dependancies from descriptions\n";
